package com.alili_tv.system.controller;

import com.alili_tv.system.common.BaseContext;
import com.alili_tv.system.common.LoginRequired;
import com.alili_tv.system.common.R;
import com.alili_tv.system.common.RedisRank;
import com.alili_tv.system.entity.Bullet;
import com.alili_tv.system.entity.User;
import com.alili_tv.system.entity.Video;
import com.alili_tv.system.entity.dto.Barrage;
import com.alili_tv.system.service.BulletService;
import com.alili_tv.system.service.UserService;
import com.alili_tv.system.service.VideoService;
import com.alili_tv.system.utils.JwtUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 弹幕表 前端控制器
 * </p>
 *
 * @author baomidou
 * @since 2023-03-17
 */
@RestController
@RequestMapping(value = "/bullet", produces = "application/json")
@Slf4j
@CrossOrigin
public class BulletController {

    @Resource
    private BulletService bulletService;

    @Resource
    private VideoService videoService;

    @Resource
    private UserService userService;

    @Resource
    private RedisRank redisRank;

    /**
     * 获取对应id的视频的弹幕
     *
     * @param id
     * @return
     */
    @GetMapping("/v3/")
    public R<List<List<Object>>> get(Long id) {

        // 查询弹幕
        // select * from bullet where video_id = #{id}
        LambdaQueryWrapper<Bullet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Bullet::getVideoId, id);
        List<Bullet> list = bulletService.list(queryWrapper);

        // 将弹幕集合转为DPlayer需要的格式
        List<List<Object>> collect = list.stream().map((item) -> {
            List<Object> li = new LinkedList<>();
            li.add(item.getTime());
            li.add(item.getType());
            li.add(item.getColor());
            li.add(item.getCreateUser());
            li.add(item.getContent());
            return li;
        }).toList();

        return R.success(collect);
    }

    /**
     * 保存弹幕
     *
     * @param barrage
     * @return
     */
    @PostMapping("/v3/")
    public R<String> save(@RequestBody Barrage barrage) {
        String token = barrage.getToken();
        if (!JwtUtils.validate(token)) {
            return R.login("请登录");
        }
        Long userId = JwtUtils.getVal(token);
        BaseContext.setCurrentId(userId);

        // DPlayer弹幕格式转为自己的数据格式
        Bullet bullet = new Bullet();
        bullet.setContent(barrage.getText());
        bullet.setColor(barrage.getColor());
        bullet.setTime(barrage.getTime());
        bullet.setVideoId(barrage.getId());
        bullet.setType(barrage.getType());
        System.out.println(bullet);

        bulletService.save(bullet);

        // 增加热度
        redisRank.incrScore(bullet.getVideoId(), 10);

        return R.success("success");
    }

    /**
     *
     * @param pageIndex 当前页数
     * @param pageSize 每页大小
     * @param timeIsAsc 是否按照弹幕出现时间排序
     * @param createTimeIsAsc 是否按照弹幕发送视频排序
     * @param videoId 查询指定的视频下的弹幕，null:全部视频，!null:指定视频
     * @return
     */
    @LoginRequired
    @GetMapping("/page")
    public R<Page<Bullet>> pageSelf(Integer pageIndex, Integer pageSize,
                                    @RequestParam(required = false) Boolean timeIsAsc,
                                    @RequestParam(required = false) Boolean createTimeIsAsc,
                                    @RequestParam(required = false) Long videoId) {
        Page<Bullet> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<Bullet> queryWrapper = new LambdaQueryWrapper<Bullet>()
                .eq(Bullet::getCreateUser, BaseContext.getCurrentId())
                .eq(videoId != null, Bullet::getVideoId, videoId)
                .orderBy(timeIsAsc != null, Boolean.TRUE.equals(timeIsAsc), Bullet::getTime)
                .orderBy(createTimeIsAsc != null, Boolean.TRUE.equals(createTimeIsAsc), Bullet::getCreateTime);

        bulletService.page(page, queryWrapper);

        if (page.getRecords().isEmpty()) {
            return R.success(page);
        }

        List<Long> userIds = new ArrayList<>();
        List<Long> videoIds = new ArrayList<>();
        page.getRecords().forEach(item -> {
            userIds.add(item.getCreateUser());
            videoIds.add(item.getVideoId());
        });

        Map<Long, User> userMap = userService.getByIds(userIds);

        LambdaQueryWrapper<Video> videoQueryWrapper = new LambdaQueryWrapper<Video>()
                .select(Video::getId, Video::getTitle)
                .in(Video::getId, videoIds);
        List<Video> videoList = videoService.list(videoQueryWrapper);
        Map<Long, Video> videoMap = new HashMap<>();
        videoList.forEach(item -> videoMap.put(item.getId(), item));

        page.getRecords().forEach(item -> {
            item.setVideo(videoMap.get(item.getVideoId()));
            item.setUser(userMap.get(item.getCreateUser()));
        });

        return R.success(page);
    }

    /**
     * 删除弹幕
     * @param ids
     * @return
     */
    @LoginRequired
    @PostMapping("/delete")
    public R<String> delete(@RequestBody List<Long> ids) {
        if (ids == null || ids.size() == 0) {
            return R.error("未选择删除的弹幕");
        }
        // 判断这些弹幕id是否是自己视频下的
        // 查询这些弹幕所属视频id
        LambdaQueryWrapper<Bullet> queryWrapper = new LambdaQueryWrapper<Bullet>()
                .select(Bullet::getVideoId)
                .in(Bullet::getId, ids);
        List<Bullet> list = bulletService.list(queryWrapper);
        Set<Long> videoIds = list.stream().map(Bullet::getVideoId).collect(Collectors.toSet());

        // 判断这些视频是否是自己发布的
        LambdaQueryWrapper<Video> videoQueryWrapper = new LambdaQueryWrapper<Video>()
                .eq(Video::getCreateUser, BaseContext.getCurrentId())
                .in(Video::getId, videoIds);
        long count = videoService.count(videoQueryWrapper);
        if (count != videoIds.size()) {
            return R.error("您没有权限删除其中的弹幕");
        }

        // 是则删除
        bulletService.removeBatchByIds(ids);

        return R.success("删除成功");
    }
}
